#include "widget.h"
#include "ui_widget.h"

#include <QFileDialog>
#include <QDebug>
#include <QMessageBox>
#include <QMenu>
#include <QSettings>

Widget::Widget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Widget)
{
    ui->setupUi(this);

    /* 读配置信息 */
    Config_Read();

    model->setReadOnly(false);
    model->setRootPath(CAT_Workspace);
    ui->treeView->setModel(model);
    ui->treeView->setRootIndex(model->index(CAT_Workspace));
    ui->treeView->setHeaderHidden(true);
    ui->treeView->setColumnHidden(1, true);
    ui->treeView->setColumnHidden(2, true);
    ui->treeView->setColumnHidden(3, true);
    ui->treeView->setEditTriggers(0);
    ui->treeView->setContextMenuPolicy(Qt::CustomContextMenu);

    ui->gBox_workspace->setTitle(tr("工作区：") + CAT_Workspace);
}

Widget::~Widget()
{
    /* 写配置信息 */
    Config_Write();

    delete ui;
}

void Widget::Config_Read()
{
    QSettings *configIniRead = new QSettings("config.ini", QSettings::IniFormat);

    CAT_Workspace = configIniRead->value("/Workspace/Path").toString();

    ui->lineEdit_keypath->setText(configIniRead->value("/Sign/File").toString());
    ui->lineEdit_keyname->setText(configIniRead->value("/Sign/User").toString());
    if ("keystore" == configIniRead->value("/Sign/Method").toString())
        ui->rButton_keystore->setChecked(true);
    else if ("testkey" == configIniRead->value("/Sign/Method").toString())
        ui->rButton_testkey->setChecked(true);
    else if ("platform" == configIniRead->value("/Sign/Method").toString())
        ui->rButton_platform->setChecked(true);
    else if ("shared" == configIniRead->value("/Sign/Method").toString())
        ui->rButton_shared->setChecked(true);
    else if ("media" == configIniRead->value("/Sign/Method").toString())
        ui->rButton_media->setChecked(true);

    ui->lineEdit_permission->setText(configIniRead->value("/ADB/Permission").toString());
    if ("push" == configIniRead->value("/ADB/Method").toString())
        ui->rButton_push->setChecked(true);
    else if ("install" == configIniRead->value("/ADB/Method").toString())
        ui->rButton_install->setChecked(true);

    delete configIniRead;
}

void Widget::Config_Write()
{
    QSettings *configIniWrite = new QSettings("config.ini", QSettings::IniFormat);

    configIniWrite->setValue("/Sign/File", ui->lineEdit_keypath->text());
    configIniWrite->setValue("/Sign/User", ui->lineEdit_keyname->text());
    if (ui->rButton_keystore->isChecked())
        configIniWrite->setValue("/Sign/Method", "keystore");
    else if (ui->rButton_testkey->isChecked())
        configIniWrite->setValue("/Sign/Method", "testkey");
    else if (ui->rButton_platform->isChecked())
        configIniWrite->setValue("/Sign/Method", "platform");
    else if (ui->rButton_shared->isChecked())
        configIniWrite->setValue("/Sign/Method", "shared");
    else if (ui->rButton_media->isChecked())
        configIniWrite->setValue("/Sign/Method", "media");

    configIniWrite->setValue("/ADB/Permission", ui->lineEdit_permission->text());
    if (ui->rButton_push->isChecked())
        configIniWrite->setValue("/ADB/Method", "push");
    else if (ui->rButton_install->isChecked())
        configIniWrite->setValue("/ADB/Method", "install");

    delete configIniWrite;
}

void Widget::RunProcess(QString cmd)
{
    myProcess = new QProcess(this);
    connect(myProcess, SIGNAL(readyReadStandardOutput()), this, SLOT(Process_Output()));
    connect(myProcess, SIGNAL(readyReadStandardError()), this, SLOT(Process_Error()));
    connect(myProcess, SIGNAL(started()), SLOT(Process_Started()));
    connect(myProcess, SIGNAL(finished(int, QProcess::ExitStatus)), SLOT(Process_Finished(int, QProcess::ExitStatus)));
    myProcess->start("cmd", QStringList() << "/c" << cmd);
}

void Widget::Process_Output()
{
    QTextCursor cursor = ui->t_Debug->textCursor();
    cursor.movePosition(QTextCursor::End);
    ui->t_Debug->setTextCursor(cursor);

    QString strTemp = QString::fromLocal8Bit(myProcess->readAllStandardOutput());
    ui->t_Debug->insertPlainText(strTemp);
}

void Widget::Process_Error()
{
    QTextCursor cursor = ui->t_Debug->textCursor();
    cursor.movePosition(QTextCursor::End);
    ui->t_Debug->setTextCursor(cursor);

    QString strTemp = QString::fromLocal8Bit(myProcess->readAllStandardError());
    ui->t_Debug->insertPlainText(strTemp);
}

void Widget::Process_Started()
{
    ui->tab_APK->setEnabled(false);
}

void Widget::Process_Finished(int exitcode, QProcess::ExitStatus status)
{
    Q_UNUSED(status);

    if (0 == exitcode)
        ui->t_Debug->insertPlainText(tr("P: 操作成功完成 \r\n\r\n"));
    else
        ui->t_Debug->insertPlainText(tr("P: 进程异常退出，错误码 %1 \r\n\r\n").arg(exitcode));

    ui->tab_APK->setEnabled(true);
}

void Widget::on_t_Debug_textChanged()
{
    QTextCursor cursor = ui->t_Debug->textCursor();
    cursor.movePosition(QTextCursor::End);
    ui->t_Debug->setTextCursor(cursor);
}

void Widget::on_pButton_loadframe_clicked()
{
    QFileDialog *fileDialog = new QFileDialog(this);
    fileDialog->setWindowTitle(tr("选择一个 Apk 文件..."));
    fileDialog->setDirectory(CAT_Workspace);
    fileDialog->setNameFilter(tr("Apk文件 (*.apk)"));
    if (fileDialog->exec() == QDialog::Accepted)
    {
        QString path = fileDialog->selectedFiles()[0];
        QString command;
        command.append("java -jar ");
        command.append(QDir::currentPath() + "/tools/apktool.jar");
        command.append(" if " + path);
        qDebug() << command << endl;

        RunProcess(command);
    }
    else
    {
        return;
    }
}

void Widget::on_treeView_customContextMenuRequested(const QPoint &pos)
{
    Q_UNUSED(pos);

    QModelIndex index = ui->treeView->currentIndex();
    QFileInfo file = QFileInfo(model->filePath(index));
    QString file_suffix = file.suffix();

    QMenu *menu = new QMenu;
    connect(menu, SIGNAL(triggered(QAction *)), this, SLOT(trigerMenu(QAction *)));
    if (true == file.isFile())
    {
        if (file_suffix == "apk" || file_suffix == "jar")
        {
            menu->addAction(QString(tr("反编译此文件")));
            menu->addSeparator();
            menu->addAction(QString(tr("签名")));
            menu->addAction(QString(tr("签名（兼容模式）")));
            menu->addAction(QString(tr("签名验证")));
            menu->addSeparator();
        }
        else
        {
            menu->addAction(QString(tr("使用 \"Notepad2\" 编辑")));
            menu->addSeparator();
        }
    }
    else
    {
        menu->addAction(QString(tr("编译此文件夹")));
        menu->addSeparator();
    }
    menu->addAction(QString(tr("重命名")));
    menu->addAction(QString(tr("删除")));
    menu->addSeparator();
    menu->addAction(QString(tr("打开文件所在目录")));
    menu->exec(QCursor::pos());
}

void Widget::trigerMenu(QAction *action)
{
    QModelIndex index = ui->treeView->currentIndex();
    QFileInfo fileInfo = QFileInfo(model->filePath(index));
    QString file = fileInfo.filePath();

    if (action->text() == tr("使用 \"Notepad2\" 编辑"))
    {
        QString command;
        command.append(QDir::currentPath() + "/tools/notepad2.exe ");
        command.append(file);
        QProcess::startDetached(command);
    }
    else if (action->text() == tr("重命名"))
        ui->treeView->edit(index);
    else if (action->text() == tr("删除"))
        model->remove(index);
    else if (action->text() == tr("打开文件所在目录"))
    {
        QString path = fileInfo.path();
        path.replace("/","\\");
        QProcess::startDetached("explorer " + path);
    }
    else if (action->text() == tr("反编译此文件"))
    {
        QString fileName = fileInfo.fileName();
        int index = fileName.lastIndexOf(".");
        fileName.truncate(index);

        QString command;
        command.append("java -jar ");
        command.append(QDir::currentPath() + "/tools/apktool.jar");
        command.append(" d " + file);
        command.append(" -f -o " + CAT_Workspace);
        if (false == CAT_Workspace.endsWith("/"))
            command.append("/");
        command.append(fileName);
        qDebug() << command << endl;

        RunProcess(command);
    }
    else if (action->text() == tr("编译此文件夹"))
    {
        QString command;
        command.append("java -jar ");
        command.append(QDir::currentPath() + "/tools/apktool.jar");
        command.append(" b " + file);
        qDebug() << command << endl;

        RunProcess(command);
    }
    else if (action->text() == tr("签名") || action->text() == tr("签名（兼容模式）"))
    {
        QString command;
        command.append("java -jar ");
        command.append(QDir::currentPath() + "/tools/apksigner.jar sign --verbose ");

        if (action->text() == tr("签名（兼容模式）"))
        {
            QDialog *dialog = new QDialog(this);
            QLineEdit *context = new QLineEdit(dialog);
            QPushButton *ok_button = new QPushButton("确定", dialog);
            dialog->setWindowTitle(tr("请指定 API Level"));
            dialog->setMinimumSize(300, 60);
            dialog->setFont(QFont("Microsoft YaHei", 9));
            context->setGeometry(15, 15, 200, 30);
            context->setValidator(new QIntValidator(1, 99, this));
            context->setAlignment(Qt::AlignCenter);
            ok_button->setGeometry(230, 14, 70, 32);
            connect(ok_button, SIGNAL(clicked()), dialog, SLOT(accept()));
            if (dialog->exec() == QDialog::Accepted)
                command.append("--min-sdk-version " + context->text() + " ");
            else
                return;
        }

        if (ui->rButton_keystore->isChecked())
            command.append("--ks " + ui->lineEdit_keypath->text() + " "
                           "--ks-key-alias " + ui->lineEdit_keyname->text() + " "
                           "--ks-pass " + ui->lineEdit_pwd->text() + " ");
        else if (ui->rButton_testkey->isChecked())
            command.append("--key " + QDir::currentPath() + "/security/testkey.pk8 "
                           "--cert " + QDir::currentPath() + "/security/testkey.x509.pem ");
        else if (ui->rButton_platform->isChecked())
            command.append("--key " + QDir::currentPath() + "/security/platform.pk8 "
                           "--cert " + QDir::currentPath() + "/security/platform.x509.pem ");
        else if (ui->rButton_shared->isChecked())
            command.append("--key " + QDir::currentPath() + "/security/shared.pk8 "
                           "--cert " + QDir::currentPath() + "/security/shared.x509.pem ");
        else if (ui->rButton_media->isChecked())
            command.append("--key " + QDir::currentPath() + "/security/media.pk8 "
                           "--cert " + QDir::currentPath() + "/security/media.x509.pem ");

        command.append("--out " + CAT_Workspace + "/[Signed_APK]/" + fileInfo.fileName());
        command.append(" " + file);
        qDebug() << command << endl;

        QDir *temp = new QDir;
        if (false == temp->exists(CAT_Workspace + "/[Signed_APK]"))
            temp->mkdir(CAT_Workspace + "/[Signed_APK]");

        RunProcess(command);
    }
    else if (action->text() == tr("签名验证"))
    {
        QString command;
        command.append("java -jar ");
        command.append(QDir::currentPath() + "/tools/apksigner.jar verify --verbose ");
        command.append(file);
        qDebug() << command << endl;

        RunProcess(command);
    }
    else
        return;
}

void Widget::on_pButton_device_clicked()
{
    QString command;
    command.append(QDir::currentPath() + "/tools/adb.exe");
    command.append(" devices");
    RunProcess(command);
}

void Widget::on_pButton_clear_clicked()
{
    ui->t_Debug->clear();
}
